/**
 * @param {string} s
 * @param {string} p
 * @return {number[]}
 */
var findAnagrams = function (s, p) {
  //结果数组result 字符串s的长度lenS 字符串p的长度lenP
  const result = []
  const lenS = s.length
  const lenP = p.length

  // 特殊情况处理：lenS<lenP时，s中不可能存在p的字母异位词，返回空数组result
  if (lenS < lenP) return result

  //字符串p中每个字符的出现频率
  let targetMap = new Array(26).fill(0)
  //字符串p中的字符的出现个数
  let targetCount = 0
  for (let char of p) {
    let index = char.charCodeAt(0) - 'a'.charCodeAt(0)
    if (targetMap[index] === 0) {
      targetCount++
    }
    targetMap[index]++
  }

  //初始化滑动窗口
  let windowMap = new Array(26).fill(0)
  //窗口的左、右边界
  let left = 0, right = 0
  //某个窗口中的有效字符的出现个数
  let valid = 0
  // 当有边界小于lenS时循环
  while (right < lenS) {
    //将s[right]放入滑动窗口，右边界右移
    let char = s[right]
    let index = char.charCodeAt(0) - 'a'.charCodeAt(0)
    right++
    //处理刚刚进入滑动窗口的s[right]的状态：更新滑动窗口和valid
    if (targetMap[index] > 0) {
      windowMap[index]++
      if (targetMap[index] === windowMap[index]) {
        valid++
      }
    }

    //当窗口宽度等于lenP时
    if ((right - left) === lenP) {
      //当滑动窗口的有效字符等于目标串的有效字符时
      if (valid === targetCount) {
        result.push(left)
      }

      //将s[left]移出滑动窗口，左边界右移
      let char = s[left]
      let index = char.charCodeAt(0) - 'a'.charCodeAt(0)
      left++
      // 处理刚刚移出滑动窗口的s[left]的状态：更新滑动窗口和valid
      if (targetMap[index] > 0) {
        if (targetMap[index] === windowMap[index]) {
          valid--
        }
        windowMap[index]--
      }
    }
  }

  //返回结果数组result
  return result
};